#ifndef _NET_CLIENT_H_
#define _NET_CLIENT_H_

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>

class NetClient{
    public:
        NetClient(){
            m_is_conn = false;
        }
        NetClient(const char* ip, int port, bool is_nonblock = true){
            m_is_conn = false;
            m_sock = Socket(is_nonblock);
            Connect(m_sock, ip, port);
        }
        ~NetClient(){
            if(m_sock > 0){
                close(m_sock);
            }
        }

        bool Connect(int sock, const char* ip, int port){
            struct hostent*     host;
            struct sockaddr_in  serv_addr;

            if((host=gethostbyname(ip))==NULL){
                return false;
            }

            serv_addr.sin_family=AF_INET;
            serv_addr.sin_port=htons(port);
            serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
            bzero(&(serv_addr.sin_zero), 8);
            if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr)) < 0){
                if (errno != EINPROGRESS) {
                    close(sock);
                    return false;
                }
                //fprintf(stderr, "Connect [%s:%d] Error\n", ip, port);
            }
            m_is_conn = true;

            return true;
        }

        inline int Socket(bool is_nonblock = true){
            int flags;
            int sock;

            if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){
                return -1;
            }

            if(is_nonblock){
                if((flags = fcntl(sock, F_GETFL, 0)) < 0) {
                    close(sock);
                    return -1;
                }
                if(fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0){
                    close(sock);
                    return -1;
                }
            }

            m_is_nonblock = is_nonblock;
            return sock;
        }

        inline int Send(void* buf, int size){
            return send(m_sock, buf, size,0);
        }
        inline int Recv(void* buf, int size){
            return recv(m_sock, buf, size, 0);
        }

        inline void Close(){close(m_sock);}
        inline bool getConnected(){return m_is_conn;}
        inline int getSocket(){return m_sock;}

    protected:
        bool    m_is_conn;
        int     m_sock;
        bool    m_is_nonblock;
};

#endif
